﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;

namespace Derbster.Domain
{
    public class Penalty : IEquatable<Penalty>
    {
        public static string Codes = "ABCEFGHILMNOPSXZ";

        [ContractVerification(false)]
        internal Penalty()
        {
            
        }

        public Penalty(Match match, Player player, string code, int period, int jamNumber, int rank)
        {
            Contract.Requires(match != null);
            Contract.Requires(player != null);
            Contract.Requires(!String.IsNullOrWhiteSpace(code));
            Contract.Requires(Codes.Contains(code));
            Contract.Requires(period == 1 || period == 2);
            Contract.Requires(jamNumber >= 1);
            Code = code;
            Match = match;
            Period = period;
            Player = player;
            JamNumber = jamNumber;
            Rank = rank;
        }

        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int PenaltyId { get; internal set; }
        public Match Match { get; internal set; }
        public int Period { get; internal set; }
        public int JamNumber { get; internal set; }
        public Player Player { get; internal set; }
        public string Code { get; internal set; }
        public int Rank { get; internal set; }

        public bool VerifyPenalty()
        {
            if (Match == null) return false;
            if (Period != 1 && Period != 2) return false;
            if (JamNumber <= 0) return false;
            if (Player == null) return false;
            if (!Codes.Contains(Code)) return false;

            return true;
        }

        public bool Equals(Penalty other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return Equals(Match, other.Match)
                && Period == other.Period
                && JamNumber == other.JamNumber
                && Equals(Player, other.Player)
                && string.Equals(Code, other.Code);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            return Equals((Penalty)obj);
        }

        public override int GetHashCode()
        {
            Contract.Assume(this.Match != null);
            unchecked
            {
                int hashCode = Period;
                hashCode = (hashCode * 397) ^ Match.GetHashCode();
                hashCode = (hashCode * 397) ^ JamNumber;
                hashCode = (hashCode * 397) ^ (Player != null ? Player.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (Code != null ? Code.GetHashCode() : 0);
                return hashCode;
            }
        }
    }
}
